#!/usr/bin/env just --justfile

# Using Just: https://github.com/casey/just?tab=readme-ov-file#installation

# List all of the available commands.
default:
  just --list

# Install any required dependencies.
setup:
	cargo install cargo-shear cargo-sort cargo-upgrades cargo-edit

# Run a localhost relay server without authentication.
relay:
	# Run the relay server overriding the provided configuration file.
	cargo run --bin moq-relay -- moq-relay/cfg/dev.toml

# Run a localhost root server, accepting connections from leaf nodes.
root: auth-key
	# Run the root server with a special configuration file.
	cargo run --bin moq-relay -- moq-relay/cfg/root.toml

# Run a localhost leaf server, connecting to the root server.
leaf: auth-token
	# Run the leaf server with a special configuration file.
	cargo run --bin moq-relay -- moq-relay/cfg/leaf.toml

# Generate a random secret key for authentication.
# By default, this uses HMAC-SHA256, so it's symmetric.
# If some one wants to contribute, public/private key pairs would be nice.
auth-key:
	@mkdir -p dev
	@if [ ! -f "dev/root.jwk" ]; then \
		rm -f dev/*.jwt; \
		cargo run --bin moq-token -- --key "dev/root.jwk" generate; \
	fi

# Generate authentication tokens for local development
# demo-web.jwt - allows publishing to demo/me/* and subscribing to demo/*
# demo-cli.jwt - allows publishing to demo/* but no subscribing
# root.jwt - allows publishing and subscribing to all paths
auth-token: auth-key
	@if [ ! -f "dev/demo-web.jwt" ]; then \
		cargo run --quiet --bin moq-token -- --key "dev/root.jwk" sign \
			--root "demo" \
			--subscribe "" \
			--publish "me" \
			> dev/demo-web.jwt ; \
	fi

	@if [ ! -f "dev/demo-cli.jwt" ]; then \
		cargo run --quiet --bin moq-token -- --key "dev/root.jwk" sign \
			--root "demo" \
			--publish "" \
			> dev/demo-cli.jwt ; \
	fi

	@if [ ! -f "dev/root.jwt" ]; then \
		cargo run --quiet --bin moq-token -- --key "dev/root.jwk" sign \
			--root "" \
			--subscribe "" \
			--publish "" \
			--cluster \
			> dev/root.jwt ; \
	fi

# Download the video and convert it to a fragmented MP4 that we can stream
download name:
	@mkdir -p dev

	@if [ ! -f dev/{{name}}.mp4 ]; then \
		curl -fsSL $(just download-url {{name}}) -o dev/{{name}}.mp4; \
	fi

	@if [ ! -f dev/{{name}}.fmp4 ]; then \
		ffmpeg -loglevel error -i dev/{{name}}.mp4 \
			-c:v copy \
			-f mp4 -movflags cmaf+separate_moof+delay_moov+skip_trailer+frag_every_frame \
			dev/{{name}}.fmp4; \
	fi

# Returns the URL for a test video.
download-url name:
	@case {{name}} in \
		bbb) echo "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" ;; \
		tos) echo "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/TearsOfSteel.mp4" ;; \
		av1) echo "http://download.opencontent.netflix.com.s3.amazonaws.com/AV1/Sparks/Sparks-5994fps-AV1-10bit-1920x1080-2194kbps.mp4" ;; \
		hevc) echo "https://test-videos.co.uk/vids/jellyfish/mp4/h265/1080/Jellyfish_1080_10s_30MB.mp4" ;; \
		*) echo "unknown" && exit 1 ;; \
	esac

# Publish a video using ffmpeg to the localhost relay server
# NOTE: The `http` means that we perform insecure certificate verification.
# Switch it to `https` when you're ready to use a real certificate.
pub name url="http://localhost:4443/anon" *args:
	# Download the sample media.
	just download {{name}}

	# Pre-build the binary so we don't queue media while compiling.
	cargo build --bin hang

	# Run ffmpeg and pipe the output to hang
	ffmpeg -hide_banner -v quiet \
		-stream_loop -1 -re \
		-i "dev/{{name}}.fmp4" \
		-c copy \
		-f mp4 -movflags cmaf+separate_moof+delay_moov+skip_trailer+frag_every_frame \
		- | cargo run --bin hang -- publish --url "{{url}}" --name "{{name}}" {{args}}


# Publish a video using ffmpeg directly from hang to the localhost
serve name:
	# Download the sample media.
	just download {{name}}

	# Pre-build the binary so we don't queue media while compiling.
	cargo build --bin hang

	# Run ffmpeg and pipe the output to hang
	ffmpeg -hide_banner -v quiet \
		-stream_loop -1 -re \
		-i "dev/{{name}}.fmp4" \
		-c copy \
		-f mp4 -movflags cmaf+separate_moof+delay_moov+skip_trailer+frag_every_frame \
		- | cargo run --bin hang -- serve --listen "[::]:4443" --tls-generate "localhost" --name "{{name}}"

# Publish the clock broadcast
# `action` is either `publish` or `subscribe`
clock action url="http://localhost:4443/anon" *args:
	@if [ "{{action}}" != "publish" ] && [ "{{action}}" != "subscribe" ]; then \
		echo "Error: action must be 'publish' or 'subscribe', got '{{action}}'" >&2; \
		exit 1; \
	fi

	cargo run --bin moq-clock -- --url "{{url}}" --broadcast "clock" {{args}} {{action}}

# Run the CI checks
check:
	cargo check --all-targets --all-features
	cargo clippy --all-targets --all-features -- -D warnings
	cargo fmt --all --check

	# requires: cargo install cargo-shear
	cargo shear

	# requires: cargo install cargo-sort
	cargo sort --workspace --check

# Run the unit tests
test:
	cargo test --all-targets --all-features

# Automatically fix some issues.
fix:
	cargo clippy --fix --allow-staged --allow-dirty --all-targets --all-features
	cargo fmt --all

	# requires: cargo install cargo-shear
	cargo shear --fix

	# requires: cargo install cargo-sort
	cargo sort --workspace

# Upgrade any tooling
upgrade:
	# Update any patch versions
	cargo update

	# Requires: cargo install cargo-upgrades cargo-edit
	cargo upgrade --incompatible

# Build the packages
build:
	cargo build
